
import com.conformiq.qtronic2.Checkpoint;
import com.conformiq.qtronic2.NotificationSink;
import com.conformiq.qtronic2.QMLArray;
import com.conformiq.qtronic2.QMLBoolean;
import com.conformiq.qtronic2.QMLNumber;
import com.conformiq.qtronic2.QMLOptional;
import com.conformiq.qtronic2.QMLRecord;
import com.conformiq.qtronic2.QMLRecordField;
import com.conformiq.qtronic2.QMLString;
import com.conformiq.qtronic2.QMLValue;
import com.conformiq.qtronic2.QMLValueVisitor;
import com.conformiq.qtronic2.ScriptBackend;
import com.conformiq.qtronic2.TimeStamp;
import com.thoughtworks.selenium.SeleneseTestCase;
import com.thoughtworks.selenium.Selenium;

public class SeleniumScriptingBackend extends ScriptBackend {

    private NotificationSink mSink = null;
    private SeleniumAdapter seleniumAdapter;
    private String sut_url;
    private String browser;
    private String speed;

    @Override
    public boolean beginScript(String dc_name) {
        mSink.notify("info", "Beginning script: " + dc_name);
        try {
            seleniumAdapter = new SeleniumAdapter();
            seleniumAdapter.setUp(sut_url, "*" + browser);
            seleniumAdapter.getSeleniumObj().setSpeed(speed);
        } catch (Exception e) {
            mSink.notify("error", e.getMessage());
        }
        return true;
    }

    @Override
    public boolean beginCase(String tc_name) {
        mSink.notify("info", "Beginning test case: " + tc_name);
        try {
            seleniumAdapter.getSeleniumObj().open(sut_url);
        } catch (Exception e) {
            mSink.notify("error", e.getMessage());
        }
        return true;
    }

    @Override
    public boolean checkpointInfo(Checkpoint cp, int status, TimeStamp ts) {
        return true;
    }

    @Override
    public boolean testStep(QMLRecord datum, String thread, String port,
            boolean isFromTester, TimeStamp ts) {
        StringBuffer data = new StringBuffer();
        ValueVisitor v = new ValueVisitor(data);
        datum.accept(v);
        try {

            if (datum.getName().equals("ClickHome")) {
            	Thread.sleep(1000);
                seleniumAdapter.getSeleniumObj().highlight("link=Home");
                seleniumAdapter.getSeleniumObj().click("link=Home");
            } 
            
            else if (datum.getName().equals("ClickAdvancedForm")) {
                seleniumAdapter.getSeleniumObj().highlight("link=Ricerca Avanzata");
                seleniumAdapter.getSeleniumObj().click("link=Ricerca Avanzata");
            } 
            
            else if (datum.getName().equals("ClickSearch")) {
            	Thread.sleep(2000);
            	String min = datum.getField("minage").getValue().toString().substring(14);
                seleniumAdapter.getSeleniumObj().type("name=Etaminima", min);
                
                String max = datum.getField("maxage").getValue().toString().substring(14);
                seleniumAdapter.getSeleniumObj().type("name=Etamassima", max);
            	
                String ambito = datum.getField("ambito").getValue().toString().substring(14);
                seleniumAdapter.getSeleniumObj().select("name=Ambito", ambito);
                
                String localita = datum.getField("localita").getValue().toString().substring(14);
                seleniumAdapter.getSeleniumObj().select("name=Localita", localita);
                
                seleniumAdapter.getSeleniumObj().click("//input[@type='submit' and @value='Cerca']");
            }
            
            else if (datum.getName().equals("ClickNormalSearch")) {
            	
            	Thread.sleep(2000);
            	              
                seleniumAdapter.getSeleniumObj().click("//input[@type='submit' and @value='Cerca']");
            } 
            
            else if (datum.getName().equals("ClickUserRegistration")) {
                seleniumAdapter.getSeleniumObj().highlight("link=privato");
                seleniumAdapter.getSeleniumObj().click("link=privato");
                } 
            
            else if (datum.getName().equals("ClickCompanyRegistration")) {
                seleniumAdapter.getSeleniumObj().highlight("link=azienda!");
                seleniumAdapter.getSeleniumObj().click("link=azienda!");
            } 
            
            else if (datum.getName().equals("ClickOnProfileFromList")) {
                System.out.println("richiesta dettagli");
                Thread.sleep(1000);
                seleniumAdapter.getSeleniumObj().highlight("link=Vai al profilo");
                seleniumAdapter.getSeleniumObj().click("link=Vai al profilo");
            }
            
            else if (datum.getName().equals("ClickLoginPage")){
            	Thread.sleep(1000);
                seleniumAdapter.getSeleniumObj().highlight("link=Login");
                seleniumAdapter.getSeleniumObj().click("link=Login");
            
            }
            
            else if (datum.getName().equals("ClickPrivati")){
            	Thread.sleep(1000);
                seleniumAdapter.getSeleniumObj().highlight("link=Privati");
                seleniumAdapter.getSeleniumObj().click("link=Privati");
            
            }
            
            else if (datum.getName().equals("ClickPrivatiBis")){
            	Thread.sleep(1000);
                seleniumAdapter.getSeleniumObj().highlight("link=Entra nell'area privati");
                seleniumAdapter.getSeleniumObj().click("link=Entra nell'area privati");
            
            }
            
            else if (datum.getName().equals("ClickIscrivitiPrivatoFromPagePrivati")){
            	Thread.sleep(1000);
                seleniumAdapter.getSeleniumObj().highlight("link=Registrati");
                seleniumAdapter.getSeleniumObj().click("link=Registrati");
            
            }
            
            else if (datum.getName().equals("ClickAziende")){
            	Thread.sleep(1000);
                seleniumAdapter.getSeleniumObj().highlight("link=Aziende");
                seleniumAdapter.getSeleniumObj().click("link=Aziende");
            
            }
            
            else if (datum.getName().equals("ClickAziendeBis")){
            	Thread.sleep(1000);
                seleniumAdapter.getSeleniumObj().highlight("link=Entra nell'area aziende");
                seleniumAdapter.getSeleniumObj().click("link=Entra nell'area aziende");
            
            }
            
            else if (datum.getName().equals("ClickIscrivitiAziendaFromPageAziende")){
            	Thread.sleep(1000);
                seleniumAdapter.getSeleniumObj().highlight("link=Registrati");
                seleniumAdapter.getSeleniumObj().click("link=Registrati");
            
            }
            
            else if (datum.getName().equals("ClickContatti")){
            	Thread.sleep(1000);
                seleniumAdapter.getSeleniumObj().highlight("link=Contatti");
                seleniumAdapter.getSeleniumObj().click("link=Contatti");
            
            }
            else if (datum.getName().equals("ClickPrivacyPolicy")){
            	Thread.sleep(1000);
                seleniumAdapter.getSeleniumObj().highlight("link=Privacy Policy");
                seleniumAdapter.getSeleniumObj().click("link=Privacy Policy");
            
            }
            else if (datum.getName().equals("ClickChiSiamo")){
            	Thread.sleep(1000);
                seleniumAdapter.getSeleniumObj().highlight("link=Chi siamo");
                seleniumAdapter.getSeleniumObj().click("link=Chi siamo");
            
            }
            
            
            else if (datum.getName().equals("RegistrationUser")) {
                String nome = datum.getField("name").getValue().toString().substring(14);
                seleniumAdapter.getSeleniumObj().type("name=nome", nome);
                
                String cognome = datum.getField("surname").getValue().toString().substring(14);
                seleniumAdapter.getSeleniumObj().type("name=cognome", cognome);
                
                seleniumAdapter.getSeleniumObj().click("name=sesso value=M");
                
                String date = datum.getField("birthdate").getValue().toString().substring(14);
                seleniumAdapter.getSeleniumObj().type("name=datanascita", date);
              
                String c = datum.getField("email").getValue().toString().substring(14);
                seleniumAdapter.getSeleniumObj().type("name=email", c);
                
                String ind = datum.getField("address").getValue().toString().substring(14);
                seleniumAdapter.getSeleniumObj().type("name=indirizzo", ind);
                
                String citt = datum.getField("nationality").getValue().toString().substring(14);
                seleniumAdapter.getSeleniumObj().type("name=cittadinanza", citt);
                
                String pass = datum.getField("password").getValue().toString().substring(14);
                seleniumAdapter.getSeleniumObj().type("name=password", pass);
                seleniumAdapter.getSeleniumObj().type("name=controllopassword", pass);
                 
                String voto = datum.getField("voto").getValue().toString().substring(14);
                seleniumAdapter.getSeleniumObj().type("name=voto", voto);
                
                String inst = datum.getField("institute").getValue().toString().substring(14);
                seleniumAdapter.getSeleniumObj().type("name=istituzione", inst);
                
                String da = datum.getField("dateschool").getValue().toString().substring(14);
                seleniumAdapter.getSeleniumObj().type("name=data", da);
                
                seleniumAdapter.getSeleniumObj().click("name=tipologia value=1");
                seleniumAdapter.getSeleniumObj().click("name=trasferte value=1");
                Thread.sleep(1000);
                seleniumAdapter.getSeleniumObj().click("name=Invia");

            } else if (datum.getName().equals("RegistrationCompany")) {
            	 Thread.sleep(1000);
            	            	 
            	String c = datum.getField("name").getValue().toString().substring(14);
                seleniumAdapter.getSeleniumObj().type("name=ragionesociale", c);
                
                String email = datum.getField("email").getValue().toString().substring(14);
                seleniumAdapter.getSeleniumObj().type("name=email", email);
                
                String pass = datum.getField("password").getValue().toString().substring(14);
                seleniumAdapter.getSeleniumObj().type("name=password", pass);
                seleniumAdapter.getSeleniumObj().type("name=controllopassword", pass);
                
                String tel = datum.getField("phone").getValue().toString().substring(14);
                seleniumAdapter.getSeleniumObj().type("name=telefono", tel);
                
                
                String re = datum.getField("location").getValue().toString().substring(14);
                seleniumAdapter.getSeleniumObj().type("name=sede", re);
                Thread.sleep(1000);
                seleniumAdapter.getSeleniumObj().click("name=Invia");
            }
            
            else if (datum.getName().equals("Back")) {
            	Thread.sleep(1000);
                seleniumAdapter.getSeleniumObj().highlight("link=Home");
                seleniumAdapter.getSeleniumObj().click("link=Home");

            } 
            
            else if (datum.getName().equals("CheckCredential")) {

                String a = datum.getField("username").getValue().toString().substring(14);

                seleniumAdapter.getSeleniumObj().type("name=pippo", a);
                String b = datum.getField("password").getValue().toString().substring(14);
                seleniumAdapter.getSeleniumObj().type("name=pluto", b);

                Thread.sleep(1000);
                seleniumAdapter.getSeleniumObj().click("name=paperino");


            } 
            
            else if (datum.getName().equals("Modifica")) {
            	Thread.sleep(1000);
                seleniumAdapter.getSeleniumObj().highlight("link=(modifica)");
                seleniumAdapter.getSeleniumObj().click("link=(modifica)");

            }else if (datum.getName().equals("ClickBack")) {
            	Thread.sleep(1000);
                seleniumAdapter.getSeleniumObj().highlight("link=Profilo");
                seleniumAdapter.getSeleniumObj().click("link=Profilo");

            }else if (datum.getName().equals("ConfirmModify")) {
            	Thread.sleep(1000);
            	String c = datum.getField("value").getValue().toString().substring(14);
            	seleniumAdapter.getSeleniumObj().highlight("name=value");
            	seleniumAdapter.getSeleniumObj().type("name=value", c );
                seleniumAdapter.getSeleniumObj().highlight("name=invia");
                Thread.sleep(3000);
                seleniumAdapter.getSeleniumObj().click("name=invia");

            }
            
            //
            //CONTROLLI OUT
            //
            
            else if (datum.getName().equals("HomePage")) {
                Thread.sleep(2000);
                //FR4 - The user must be able to access the following pages: Home, Chi Siamo, Privati, Aziende, Contatti, Privacy Policy, Log-In
                SeleneseTestCase.assertTrue(seleniumAdapter.getSeleniumObj().getLocation().toString().contains("home"));
                Thread.sleep(1000);

            }
            
            else if (datum.getName().equals("IndexPage")) {
                Thread.sleep(2000);
                
                //FR4 - The user must be able to access the following pages: Home, Chi Siamo, Privati, Aziende, Contatti, Privacy Policy, Log-In
                if(seleniumAdapter.getSeleniumObj().isElementPresent("link=Logout")){
                	seleniumAdapter.getSeleniumObj().click("link=Logout");
                	SeleneseTestCase.assertTrue(seleniumAdapter.getSeleniumObj().getLocation().toString().contains("home"));
                }
                else{
                	SeleneseTestCase.assertTrue(seleniumAdapter.getSeleniumObj().getLocation().toString().contains("index"));
                }
                Thread.sleep(1000);
            }
            
            else if (datum.getName().equals("ChiSiamo")) {
                Thread.sleep(2000);
              //FR4 - The user must be able to access the following pages: Home, Chi Siamo, Privati, Aziende, Contatti, Privacy Policy, Log-In
                SeleneseTestCase.assertTrue(seleniumAdapter.getSeleniumObj().getLocation().toString().contains("chisiamo"));
                Thread.sleep(1000);

            }
            
            else if (datum.getName().equals("Privati")) {
                Thread.sleep(2000);
              //FR4 - The user must be able to access the following pages: Home, Chi Siamo, Privati, Aziende, Contatti, Privacy Policy, Log-In
                SeleneseTestCase.assertTrue(seleniumAdapter.getSeleniumObj().getLocation().toString().contains("privati"));
                Thread.sleep(1000);
            }
            
            else if (datum.getName().equals("Aziende")) {
                Thread.sleep(2000);
              //FR4 - The user must be able to access the following pages: Home, Chi Siamo, Privati, Aziende, Contatti, Privacy Policy, Log-In
                SeleneseTestCase.assertTrue(seleniumAdapter.getSeleniumObj().getLocation().toString().contains("aziende"));
                Thread.sleep(1000);
            }
            
            else if (datum.getName().equals("PrivacyPolicy")) {
                Thread.sleep(2000);
              //FR4 - The user must be able to access the following pages: Home, Chi Siamo, Privati, Aziende, Contatti, Privacy Policy, Log-In
                SeleneseTestCase.assertTrue(seleniumAdapter.getSeleniumObj().getLocation().toString().contains("privacy"));
                Thread.sleep(1000);

            }
            
            else if (datum.getName().equals("Contatti")) {
                Thread.sleep(2000);
              //FR4 - The user must be able to access the following pages: Home, Chi Siamo, Privati, Aziende, Contatti, Privacy Policy, Log-In
                SeleneseTestCase.assertTrue(seleniumAdapter.getSeleniumObj().getLocation().toString().contains("contatti"));
                Thread.sleep(1000);

            }
            
            else if (datum.getName().equals("AdvancedSearchForm")) {
                Thread.sleep(1000);
                SeleneseTestCase.assertTrue(seleniumAdapter.getSeleniumObj().getLocation().toString().contains("ricercaavanzata"));
                Thread.sleep(1000);

            }else if (datum.getName().equals("Profile")) {
            	Thread.sleep(1000);
            	
            	//FR1 - The key object which has be stored is the curriculum vitae
            	//FR2 - The website must be able to manage different kind of users: administrators, registered users, registered company and anonymous users  - Company and User
                
            	//FR5 - The user must be able to register as a company
            	//FR6 - The user must be able to register as a private user
                SeleneseTestCase.assertTrue(seleniumAdapter.getSeleniumObj().getLocation().toString().contains("profilo"));
                SeleneseTestCase.assertFalse(seleniumAdapter.getSeleniumObj().isElementPresent("link=Leggi"));
                Thread.sleep(1000);
            }
            
            else if (datum.getName().equals("Admin")) {
            	Thread.sleep(1000);
            	
            	//FR2 - The website must be able to manage different kind of users: administrators, registered users, registered company and anonymous users  - Admin
                SeleneseTestCase.assertTrue(seleniumAdapter.getSeleniumObj().getLocation().toString().contains("profilo"));
                SeleneseTestCase.assertTrue(seleniumAdapter.getSeleniumObj().isElementPresent("link=Leggi"));
                Thread.sleep(1000);
            }
            
            else if (datum.getName().equals("ErrorPageAdvancedSearch")) {
            	//FR10 - Each type of user should be able to perform a search
                SeleneseTestCase.assertTrue(seleniumAdapter.getSeleniumObj().isElementPresent("id=errore"));
                Thread.sleep(1000);

            }
            
            else if (datum.getName().equals("ErrorPageLogin")) {
            	Thread.sleep(1000);
                SeleneseTestCase.assertTrue(seleniumAdapter.getSeleniumObj().getLocation().toString().contains("error=true"));
                Thread.sleep(1000);

            }
            
            else if (datum.getName().equals("ErrorPageUserRegistration")) {
            	  Thread.sleep(1000);

            	  //FR7 - Registration must provide an error page if the login credentials are already used - User
            	SeleneseTestCase.assertTrue(seleniumAdapter.getSeleniumObj().isElementPresent("id=errore"));
                Thread.sleep(1000);

            }
            
            else if (datum.getName().equals("ErrorPageCompanyRegistration")) {
            	  Thread.sleep(1000);
            	  //FR7 - Registration must provide an error page if the login credentials are already used - Company
            	SeleneseTestCase.assertTrue(seleniumAdapter.getSeleniumObj().isElementPresent("id=errore"));
                Thread.sleep(1000);

            }
            
            else if (datum.getName().equals("ShowContactResults")) {
                Thread.sleep(1000);
                
                //FR9 -  Each registered company must be able to perform a search 
                //FR10 - Each type of user should be able to perform a search
                SeleneseTestCase.assertTrue(seleniumAdapter.getSeleniumObj().getLocation().toString().contains("ricerca?"));
                Thread.sleep(1000);

            }
            
            else if (datum.getName().equals("LoginPage")) {
                Thread.sleep(1000);
                //FR4 - The user must be able to access the following pages: Home, Chi Siamo, Privati, Aziende, Contatti, Privacy Policy, Log-In 
                SeleneseTestCase.assertTrue(seleniumAdapter.getSeleniumObj().getLocation().toString().contains("loginpage"));
                Thread.sleep(1000);

            }
            
            else if (datum.getName().equals("DetailedContactPage")) {
                Thread.sleep(1000);
              //FR03 - The website must provide two types of views: a public view and a complete view/Complete View
                SeleneseTestCase.assertTrue(seleniumAdapter.getSeleniumObj().getLocation().toString().contains("profilosingolo?id="));
                SeleneseTestCase.assertTrue(seleniumAdapter.getSeleniumObj().isElementPresent("//img[@alt='Foto non disponibile']"));
                Thread.sleep(1000);

            }
            
            else if (datum.getName().equals("DetailedContactPageLimited")) {
                Thread.sleep(1000);
                //FR03 - The website must provide two types of views: a public view and a complete view/Public View
                SeleneseTestCase.assertTrue(seleniumAdapter.getSeleniumObj().getLocation().toString().contains("profilosingolo?id="));
                SeleneseTestCase.assertFalse(seleniumAdapter.getSeleniumObj().isElementPresent("//img[@alt='Foto non disponibile']"));
                Thread.sleep(1000);

            }
            
            else if (datum.getName().equals("UserRegistrationPage")) {
                Thread.sleep(1000);
                SeleneseTestCase.assertTrue(seleniumAdapter.getSeleniumObj().getLocation().toString().contains("iscrivitiprivato"));
                Thread.sleep(1000);

            }
            
            else if (datum.getName().equals("CompanyRegistrationPage")) {
                Thread.sleep(1000);
                SeleneseTestCase.assertTrue(seleniumAdapter.getSeleniumObj().getLocation().toString().contains("iscrivitiazienda"));
                Thread.sleep(1000);

            }
            
            else if (datum.getName().equals("ModificaPage")) {
                Thread.sleep(1000);
                //FR8 - Description: Each registered user or registered company must be able to modify his curriculum at any time
                SeleneseTestCase.assertTrue(seleniumAdapter.getSeleniumObj().getLocation().toString().contains("modifica"));
                Thread.sleep(1000);

            } 
            
        } catch (Exception e) {
            mSink.notify("error", e.getMessage());
        }
        return true;
    }

    @Override
    public boolean internalCommunicationsInfo(QMLRecord datum, String sender,
            String receiver, String port,
            TimeStamp ts) {
        return true;
    }

    @Override
    public boolean endCase() {
        mSink.notify("info", "Ending test case");
        return true;
    }

    @Override
    public boolean endScript() {
        mSink.notify("info", "Ending script");
        return true;
    }

    @Override
    public void caseProbability(double probability) {
    }

    @Override
    public boolean setConfigurationOption(String property, String value) {
        mSink.notify("info", "Set configuration option '" + property
                + " to '" + value + "'");
        if ("SeleniumConfig.sut_url".equals(property)) {
            sut_url = value;
        } else if ("SeleniumConfig.browser".equals(property)) {
            browser = value;
        } else if ("SeleniumConfig.speed".equals(property)) {
            speed = value;
        }
        return true;
    }

    @Override
    public boolean trace(String message, TimeStamp time) {
        return true;
    }

    @Override
    public void setNotificationSink(NotificationSink sink) {
        mSink = sink;
    }

    /**
     * Value visitor for rendering QML values.
     */
    class ValueVisitor implements QMLValueVisitor {

        public ValueVisitor(StringBuffer out) {
            mOut = out;
        }

        /**
         * Visit a QML array.
         */
        public void visit(QMLArray a) {
            mOut.append("{ ");
            int n = a.getNumberOfElements();
            if (n < 1) {
                mOut.append("'empty array'");
            } else {
                for (int i = 0; i < n; i++) {
                    if (i > 0) {
                        mOut.append(", ");
                    }
                    a.getValue(i).accept(this);
                }
            }
            mOut.append(" }");
        }

        /**
         * Visit a QML boolean.
         */
        public void visit(QMLBoolean b) {
            mOut.append(b.getValue() ? "true" : "false");
        }

        /**
         * Visit a QML number.
         */
        public void visit(QMLNumber n) {
            if (n.isBigInteger()) {
                mOut.append(n.getBigInteger());
            } else {
                mOut.append(n.getNumerator());
                mOut.append("/");
                mOut.append(n.getDenominator());
            }
        }

        /**
         * Visit a QML record.
         */
        public void visit(QMLRecord r) {
            for (int i = 0, n = r.getNumberOfFields(); i < n; i++) {
                QMLRecordField f = r.getField(i);
                QMLValue v = f.getValue();
                if (v != null) {
                    v.accept(this);
                } else {
                    mOut.append("null");
                }
            }
        }

        /**
         * Visit a QML string.
         */
        public void visit(QMLString s) {
            if (s.getValue().equals("")) {
                mOut.append("\"\"");
            } else {
                mOut.append("\"" + s.getValue() + "\"");
            }
        }

        /**
         * Visit a QML optional type.
         */
        public void visit(QMLOptional p) {
            if (p.isPresent()) {
                mOut.append("optional: ");
                p.getValue().accept(this);
            } else {
                mOut.append("'omitted field'");
            }
        }
        private StringBuffer mOut = null;
    }

    public class SeleniumAdapter extends SeleneseTestCase {

        public Selenium getSeleniumObj() {
            return this.selenium;
        }
    }
}